package com.example.archive.util;

import com.example.archive.service.OCRService;
import com.example.archive.entity.Category;
import com.example.archive.entity.Tag;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class NLPProcessor {

    @Autowired
    private OCRService ocrService;

    public String extractText(MultipartFile file) throws IOException {
        String contentType = file.getContentType();
        InputStream inputStream = file.getInputStream();

        if (contentType == null) {
            return "";
        }

        if (contentType.equals("application/pdf")) {
            try (PDDocument document = PDDocument.load(inputStream)) {
                PDFTextStripper pdfTextStripper = new PDFTextStripper();
                return pdfTextStripper.getText(document);
            }
        } else if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
            try (XWPFDocument document = new XWPFDocument(inputStream)) {
                XWPFWordExtractor extractor = new XWPFWordExtractor(document);
                return extractor.getText();
            }
        } else if (contentType.equals("text/plain")) {
            // Java 8 compatible way to read all bytes from InputStream
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int nRead;
            byte[] data = new byte[1024];
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            return new String(buffer.toByteArray());
        } else if (isImageFile(contentType)) {
            // 使用OCR识别图片中的文字
            try {
                return ocrService.recognizeText(file);
            } catch (Exception e) {
                return "OCR识别失败: " + e.getMessage();
            }
        } else {
            // 对于其他类型文件，返回空字符串
            return "";
        }
    }

    /**
     * 从已保存的文件中提取文本内容
     * 用于避免MultipartFile输入流消耗问题
     * 
     * @param file 已保存的文件
     * @return 提取的文本内容
     * @throws IOException 文件读取异常
     */
    public String extractTextFromFile(File file) throws IOException {
        if (!file.exists()) {
            return "";
        }

        // 根据文件扩展名判断文件类型
        String fileName = file.getName().toLowerCase();
        
        if (fileName.endsWith(".pdf")) {
            try (FileInputStream fis = new FileInputStream(file);
                 PDDocument document = PDDocument.load(fis)) {
                PDFTextStripper pdfTextStripper = new PDFTextStripper();
                return pdfTextStripper.getText(document);
            }
        } else if (fileName.endsWith(".docx")) {
            try (FileInputStream fis = new FileInputStream(file);
                 XWPFDocument document = new XWPFDocument(fis)) {
                XWPFWordExtractor extractor = new XWPFWordExtractor(document);
                return extractor.getText();
            }
        } else if (fileName.endsWith(".txt")) {
            return new String(Files.readAllBytes(file.toPath()));
        } else if (isImageFile(fileName)) {
            // 使用OCR识别图片中的文字
            try {
                return ocrService.recognizeText(Files.readAllBytes(file.toPath()));
            } catch (Exception e) {
                return "OCR识别失败: " + e.getMessage();
            }
        } else {
            // 对于其他类型文件，返回空字符串
            return "";
        }
    }

    /**
     * 判断是否为图片文件
     * 支持根据contentType或文件名判断
     */
    private boolean isImageFile(String input) {
        if (input == null) return false;
        
        // 判断是否为contentType格式
        if (input.contains("/")) {
            return input.equals("image/jpeg") ||
                   input.equals("image/jpg") ||
                   input.equals("image/png") ||
                   input.equals("image/gif") ||
                   input.equals("image/bmp") ||
                   input.equals("image/webp");
        } 
        // 判断是否为文件名格式
        else {
            String fileName = input.toLowerCase();
            return fileName.endsWith(".jpg") ||
                   fileName.endsWith(".jpeg") ||
                   fileName.endsWith(".png") ||
                   fileName.endsWith(".gif") ||
                   fileName.endsWith(".bmp") ||
                   fileName.endsWith(".webp");
        }
    }

    public String analyzeCategory(String text, List<Category> categories) {
        text = text.toLowerCase();
        
        // 首先尝试匹配数据库中的分类
        if (categories != null && !categories.isEmpty()) {
            for (Category category : categories) {
                String categoryName = category.getCategoryName().toLowerCase();
                String description = category.getDescription() != null ? category.getDescription().toLowerCase() : "";
                
                // 基于分类名称进行匹配
                if (text.contains(categoryName)) {
                    return category.getCategoryName();
                }
                
                // 基于分类描述进行匹配
                if (!description.isEmpty() && text.contains(description)) {
                    return category.getCategoryName();
                }
            }
        }
        
        // 如果数据库匹配失败，使用硬编码的关键词匹配
        if (text.contains("公共") || text.contains("政府") || text.contains("政策")) {
            return "公共档案";
        } else if (text.contains("个人") || text.contains("简历") || text.contains("身份")) {
            return "个人档案";
        } else if (text.contains("受限") || text.contains("机密") || text.contains("秘密")) {
            return "受限档案";
        } else if (text.contains("公告") || text.contains("通知") || text.contains("发布")) {
            return "企业公告";
        } else if (text.contains("培训") || text.contains("课程") || text.contains("学习")) {
            return "培训资料";
        }
        return "其他"; // Default category
    }

    public String analyzeTags(String text, List<Tag> tags) {
        Set<String> matchedTags = new HashSet<>();
        text = text.toLowerCase();
        
        // 首先尝试匹配数据库中的标签
        if (tags != null && !tags.isEmpty()) {
            for (Tag tag : tags) {
                String tagName = tag.getTagName().toLowerCase();
                String description = tag.getDescription() != null ? tag.getDescription().toLowerCase() : "";
                
                // 基于标签名称进行匹配
                if (text.contains(tagName)) {
                    matchedTags.add(tag.getTagName());
                }
                
                // 基于标签描述进行匹配
                if (!description.isEmpty() && text.contains(description)) {
                    matchedTags.add(tag.getTagName());
                }
            }
        }
        
        // 如果数据库匹配没有结果，使用硬编码的关键词匹配
        if (matchedTags.isEmpty()) {
            if (text.contains("报告")) matchedTags.add("报告");
            if (text.contains("会议")) matchedTags.add("会议");
            if (text.contains("财务")) matchedTags.add("财务");
            if (text.contains("合同")) matchedTags.add("合同");
            if (text.contains("项目")) matchedTags.add("项目");
            if (text.contains("协议")) matchedTags.add("协议");
            if (text.contains("计划")) matchedTags.add("计划");
            if (text.contains("纪要")) matchedTags.add("纪要");
            if (text.contains("法律")) matchedTags.add("法律");
            if (text.contains("技术")) matchedTags.add("技术");
            if (text.contains("档案")) matchedTags.add("档案");
            if (text.contains("文件")) matchedTags.add("文件");
            if (text.contains("资料")) matchedTags.add("资料");
        }

        return String.join(",", matchedTags);
    }
} 